<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <!--<base href="www.baidu.com"/>-->
    <title>css 进阶</title>
    <style>
        p{
            /*font: 14px/1em sans-serif;*/
            white-space: pre;
        }
        #selector > article p::first-letter {
            font-size: 28px;
            color: red;
        }
        ul > li{
            white-space: pre-line;
        }
        .important{
            color: red !important;
        }
    </style>
</head>
<body>
    <nav>
        <ul>
            <li><a href="#selector">选择器</a></li>
            <li><a href="#special">特殊性/继承/层叠</a></li>
        </ul>
    </nav>
    <section id="selector">
        <article>
            <h1 class="warning">元素/类选择器:</h1>
            <pre>
                .warning: 其实是 *.warning;
                也即,类选择器前面是可以带上元素的
                p.warning: 这才是类选择的最本质的用法
                但如无特殊情况，建议不要在 .class 选择前面加元素过滤
            </pre>
        </article>
        <article>
            <h1>多类选择器</h1>
            <pre>
                p.warning.urgent: 选择带有两个class的p元素.
                注意类名之间是没有空格的,如果有,那是选择子元素!
                p.warning .urgent: 选择 类名为warning的p元素 的类名为urgent的子元素
            </pre>
        </article>
        <article>
            <h1>属性选择器</h1>
            <pre>
                img[alt] 选择alt属性不为空的img元素
                p[foo="bar"]
                没有属性不等于某值的选择器。
                故要对多种input选择，只能
                input[type="text],
                input[type="password"]{
                    /*这样一个个地敲*/
                }
                这里要注意不指定属性则会选择不到的坑.
            </pre>
        </article>
        <article>
            <h1>根据文档结构来选择</h1>
            <p>
                <span>后代选择器/根据上下文来选择</span>
                <pre>
                    h1 em  
                    在 h1 中的后代中找到所有 em 元素,不管嵌套有多深
                    注意到,这里是有空格的,同理,如果类名之前也带空格,那也是根据上下文来选择,而不是多类选择
                </pre>
            </p>
            <p>
                <span>子类选择器</span>
                <pre>
                    h1 > em 
                    这样效率会高点,因为只选择直接子类。
                    注意: "这样写效率高点" 只适用于CSS选择器上，如果在jQuery中，$('h1').children('em')效率更高，因为少了匹配符>的解析
                </pre>
            </p>
            <p>
                <span>选择下一个兄弟元素</span>
                <pre>
                    h1 + h2 
                </pre>
            </p>
            <p>
                <span>选择后面的所有兄弟元素</span>
                <pre>
                    h1 ~ h2
                    选择 h1 元素后面的所有 h2 元素
                </pre>
            </p>
            <span class="important">注意: 没有选择上一个兄弟元素的选择器 </span>
        </article>
        <article>
            <h1>伪类与伪元素</h1>
            <pre>
                一个冒号开头的是伪类，两个冒号开头的是伪元素.虽然在CSS里一般写成一个冒号都可以，但最好遵循规范。
                <span class="important">伪类一般与状态有关,可以认为是CSS选择器内置的类，与开发人员自定义的类区分开来(个人观点,帮助理解)</span>
                常见伪类：
                :hover 鼠标悬停时
                :active 鼠标按下去时
                :focus 获得焦点时
                :first-child 某某元素作为第一个子元素 
                :last-child 某某元素作为最后一个子元素
                :nth-child(n) 某某元素作为第n个子元素
                
                把:first-child讲清楚，这个很容易被误解，就像最初我的一样(其他的道理是一样的)
                考虑以下dom结构(示意)
                div
                   p p1 p
                   p p2 p
                   p p3 p
                div
                则 p:first-child 指的是p1, 因为它意为：选择p元素，它是属于对于其父结点而言的第一个子元素
   
                <span class="important"> 伪元素则是元素，因不存在于DOM文档中，故称为伪元素，与真正的元素区分开来. </span>
                
                常见伪元素：
                ::before
                ::after
                
                注意：
                1. 伪元素是存在于真正的元素边框内部的
                2.以上两种伪元素在使用时，必须设置content属性，即使是空字符串 content:'';也可以，否则是不会显示出来的
                更多内容请看:
                https://segmentfault.com/a/1190000000484493
                
                
                另:
                ::first-letter 只能应用于块级元素
                但考虑这种情况:
                p
                  span hello
                p本身没有文本节点,则还是应用到 span 的 hello 内容上
            </pre>
            <p>
                待试验的段落
            </p>
        </article>
    </section>
    <section id="special">
        <article>
            <h1>特殊性,也即选择器的权重</h1>
            <ul>
                <li>ID选择: 0,1,0,0</li>
                <li>类选择/属性选择/伪类: 0,0,1,0</li>
                <li>元素选择/伪元素: 0,0,0,1
                    结合符(>)/通配符(*)不增加权重
                </li>
                <li>为什么以上都是以0开头的?因为第一个位置是为内联样式保留的!
                    选择器中最吊的是内联样式:1,0,0,0
                    <span class="important">
                        因此，千万不要写内联样式，代码难看还倒是其次，关键是内联样式很难修改。
                        只能通过js或者使用下面介绍的important声明才能修改
                    </span>
                </li>
            </ul>
        </article>
        <article>
            <h1>重要性</h1>
            <pre>
                !important 作为重要声明,如：
                color: red !important;
                
                重要声明总是胜出于非重要声明.
                可以试试下面的内联样式:style="color:black".
                可见内联样式都被覆盖了!!!
            </pre>
            <span class="important" style="color: black">important</span>
            <p>重要声明一共有5级,权重由大到小排列如下:</p>
            <ol>
                <li>读者的重要声明</li>
                <li>创作人员的重要声明</li>
                <li>创作人员的正常声明</li>
                <li>读者的正常声明</li>
                <li>用户代理的默认样式</li>
            </ol>
            <span class="important">一般而言,正常声明就可以了，不要乱写important声明</span>
            
        </article>
        <article>
            <h1>继承</h1>
            <p>
                基于继承机制,样式不仅应用到指定的元素,还会应用到它的后代元素.
                值不会向上传播.
                只有一个例外:
                body元素的背景样式可以传递到html元素,相应地可以定义画布.

                继承的值根本没有特殊性,也即比0还要小.这一点绝不能等闲视之.
                那这到底是什么意思呢?考虑下面的情况：
                
                div class="repeat-setting font52"
                    p class="setting-title" 重复 p
                div
                
                根据继承, p 元素继承了父结点的font52这个类，即字体大小为52px,
                但由于使用的mui框架预设定了样式
                
                p {
                    font-size: 14px;
                }
                
                虽然权重很小，却也比继承的权重要大,因而元素 p 不能按预期显示大小为 52px 的字体,
                一个简单的解决办法是：为 p 元素也添加class font52 
                
                <span class="important">这就提醒我们：谨慎地使用通配符,小心地使用元素选择器，还有，不要太相信继承</span>

                另：
                不能继承的值: 盒子模型(margin,padding,background), border 都不能继承
            </p>
        </article>
        <article>
            <h1>层叠</h1>
            <p>
                当重要性/特殊性都相同时,
                一个声明的样式在文档的越后面出现,其权重就越大.
                即：
                
                .test{
                    color: blue;
                }
                
                .test{
                    color: red;
                }
                
                则最终 .test 的颜色为红色

                正是因为上面的规则,所以通常推荐链接样式的顺序为 LVHA:
                :link {}
                :visited {}
                :hover {}
                :active {}

                但其实有种简单的办法可以预防冲突,即将伪类链接到一起:
                :link {color:blue;}
                :visited {color:purple;}
                :link:hover {color:red;}
                :visited:hover {color:gray;}
                :link:active {color:orange;}
                :visited:hover {color:silver;}
                但这种方法,低版本的IE不支持?还好我们已经不用考虑IE6了,详见《CSS权威指南》P62
            </p>
        </article>
    </section>
    <script>
        var log = function(msg){
            console.log(msg);
        };

        window.onload = function(){
            log(document.querySelector('h1.warning'));

            var sections = document.getElementsByTagName('section');
            for(var i = 0; i < sections.length; i++){
                if(i != 0){
                    sections[i].style.display = 'none';
                }
            }

            var links = document.getElementsByTagName('nav')[0]
                    .getElementsByTagName('a');
            for(var i = 0; i < links.length; i++){
//                var id = links[i].getAttribute('href').split('#')[1];
                links[i].sectionId = links[i].getAttribute('href').split('#')[1];

                links[i].onclick = function(){
//                    log(this.sectionId)
                    //一直是一个引用来的
//                    log(id);
                    for(var i = 0; i < sections.length; i++){
                        if(this.sectionId == sections[i].getAttribute('id')){
                            sections[i].style.display='block';
                        }
                        else{
                            sections[i].style.display='none';
                        }
                    }
                }
            }
        }
    </script>
</body>
</html>